﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using RattlerRace;

namespace RattlerRaceGUI
{
    public partial class GUI : Form
    {
        private Timer _ticks;
        private Level _level;
        private bool _speed;
        private int _prevDirection; //da ne moremo spremeniti smeri npr. 0 takoj v 2
        private List<int> _povecajKaco;
        private int _pressedKey;
        private bool _paused;
        private int _points;
        private int _izbraniLevel = 0;
        private Wall _stena = new Wall();
        private Bitmap _jabolkoSlika;
        private Bitmap _goldApple;
        private Bitmap _glavaSlika;
        private Bitmap _goScreen;
        private Bitmap _startScreen;
        private static String _playerName;
        private static ScoreTextHandler _sth;
        private int _snakeNum;
        private int _ballNum;
        private bool _doorOpen;
        private int _randomTest;
        private bool _removingSnake;
        private Random _random4Apples;

        public static ScoreTextHandler Sth
        {
            get { return _sth; }
            set { _sth = value; }
        }

        public static String PlayerName
        {
            get { return _playerName; }
            set { _playerName = value; }
        }

        private int _lives;

        private int premik_y = 30;

        private int _difficulty, _difficultyFactor;
        //private Snake _kacica;

        public GUI()
        {
            InitializeComponent();
            _snakeNum = 1;
            _ballNum = 2;
            _povecajKaco = new List<int>();
            _ticks = new Timer();
            _level = new Level();
            _jabolkoSlika = new Bitmap("../../Resources/apple_gfx.png");
            _goldApple = new Bitmap("../../Resources/apple-gold_gfx.png");
            _glavaSlika = new Bitmap("../../Resources/snake-head_gfx.png");
            _goScreen = new Bitmap("../../Resources/gowsnake.png");
            _startScreen = new Bitmap("../../Resources/rrwsnake.png");
            _playerName = "aaa";
            _sth = new ScoreTextHandler();
            _doorOpen = false;
            _sth.loadScores();
            _ticks.Tick += new EventHandler(Update); //update funkcija
            _ticks.Start();
            this.KeyDown += new KeyEventHandler(Form1_keyDown); //zaznava tipk
            _paused = false;
            _lives = 3;
            igralnoOkno.Image = _startScreen;
            _paused = true;
            _randomTest = 500;
            _removingSnake = false;
            _random4Apples = new Random();
            //startGame();
            //_kacica = new Snake();
        }

        private void startGame()
        {
            pictureBox1.BackColor = Color.Green;
            pictureBox1.Width = 287;
            diffucultySetup();
            label1.Text = "000000";
            _points = 0;
            _doorOpen = false;
            _level.generate(_izbraniLevel, _snakeNum, _ballNum);
            _level.Level_number = _izbraniLevel;
            _pressedKey = -10;
            _prevDirection = 0;
            setSpeed(false);
            _povecajKaco.Clear();
            for(int i=0; i<4; i++)
                _povecajKaco.Add(0); //player
            _paused = false;
            _removingSnake = false;
           
        }

        private void continueGame()
        {
            diffucultySetup();
            pictureBox1.BackColor = Color.Green;
            pictureBox1.Width = 287;
            String nule = "000000";
            String tocke = _points.ToString();
            label1.Text = nule.Substring(0, 6 - tocke.Length) + tocke;
            _doorOpen = false;
            _level.generate(_izbraniLevel, _snakeNum, _ballNum);
            _pressedKey = -10;
            _prevDirection = 0;
            setSpeed(false);
            _povecajKaco.Clear();
            _povecajKaco.Add(0); //player
            _povecajKaco.Add(0); //opponent
        }

        /// <summary>
        /// Pravilno nastavi težavnost in GUI.
        /// Denis Jakoša
        /// </summary>
        private void diffucultySetup()
        {
            _difficulty = UserSettings.getDifficulty();
            if(_difficulty == 0)
            {
                beginnerToolStripMenuItem.Checked = true;
                _difficultyFactor = DifficultyLevels.Easy;
            }
            else if (_difficulty == 1)
            {
                intermediateToolStripMenuItem.Checked = true;
                _difficultyFactor = DifficultyLevels.Intermediate;
            }
            else if (_difficulty == 2)
            {
                advancedToolStripMenuItem.Checked = true;
                _difficultyFactor = DifficultyLevels.Advanced;
            }
            else if (_difficulty == 3)
            {
                expertToolStripMenuItem.Checked = true;
                _difficultyFactor = DifficultyLevels.Expert;
            }
        }

        /// <summary>
        /// Tu se nastavlja hitrost ©Tomaž Avberšek
        /// </summary>
        /// <param name="speedUp"></param>
        private void setSpeed(bool speedUp)
        {
            if (speedUp)
                _ticks.Interval = 1000 / DifficultyLevels.Expert;
            else
                _ticks.Interval = 1000 / _difficultyFactor;
        }

        /// <summary>
        /// Event, ki zazna pritisnjeno tipko ©Tomaž Avberšek
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_keyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Up)
                _pressedKey = 0;
            else if (e.KeyCode == Keys.Right)
                _pressedKey = 1;
            else if (e.KeyCode == Keys.Down)
                _pressedKey = 2;
            else if (e.KeyCode == Keys.Left)
                _pressedKey = 3;

            //dodano za enter in escape, če se nuca
            else if (e.KeyCode == Keys.Enter)
                _pressedKey = 10;
            else if (e.KeyCode == Keys.Escape)
                _pressedKey = 20;
            else if (e.KeyCode == Keys.P)
            {
                if (_paused)
                {
                    _paused = false;
                }
                else
                {
                    _paused = true;
                }
            }
        }
        
        /// <summary>
        /// Update funkcija, ki jo kliče obravnava event od timerja ©Tomaž Avberšek
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Update(object sender, EventArgs e)
        {
            if (!_paused)
            {
                _speed = false;
                List<int> state = new List<int>();
                state.Add(0);
                state.Add(0);
                if (_pressedKey != -10) //če je se je zgodil event za pritisk tipke, potem gre dalje preverjat, katera tipka je bila pritisnjena
                {
                    if (_pressedKey == 3 && _prevDirection != 1 && _level.Snakes[0].Body[0].Smer == 3) //levo
                    {
                        _speed = true;
                        _prevDirection = 3;
                    }
                    else if (_pressedKey == 1 && _prevDirection != 3 && _level.Snakes[0].Body[0].Smer == 1) //desno
                    {
                        _speed = true;
                        _prevDirection = 1;
                    }
                    else if (_pressedKey == 0 && _prevDirection != 2 && _level.Snakes[0].Body[0].Smer == 0) //gor
                    {
                        _speed = true;
                        _prevDirection = 0;
                    }
                    else if (_pressedKey == 2 && _prevDirection != 0 && _level.Snakes[0].Body[0].Smer == 2) //doli
                    {
                        _speed = true;
                        _prevDirection = 2;
                    }
                    if (_pressedKey != (_prevDirection + 2) % 4)
                        _prevDirection = _pressedKey;
                    _pressedKey = -10; //ponastavimo tipko
                }

                state = _level.updateGameGrid(_prevDirection, ref _povecajKaco, _doorOpen); /*metoda zazna, če je prišlo do trka oz. če je kača pojedla jabolko. Sicer samo posodobi položaj kaće v game_gridu*/
                setSpeed(_speed); //nastavi hitrost tick-ov (update speed)
                {
                    if (state[0] == 1) //kača je pojedla jabolko (dodajo se 4 elementi na rep, po 1 element na posamezen "tick")
                    {
                        _povecajKaco[0] += 4;
                        _points = int.Parse(label1.Text);
                        _points += 30;
                        //_level.Snakes[0].Dosezene_tocke.CurrentPoints += 30;
                        if (Points.endsWith50(_points) && _lives < 3)
                        {
                            _lives++;
                        }
                        String nule = "000000";
                        String tocke = _points.ToString();
                        label1.Text = nule.Substring(0, 6 - tocke.Length) + tocke;
                    }
                    else if (state[0] == -1) //prišlo je do trka
                    {
                        _lives--;
                        pictureBox1.BackColor = Color.Green;
                        pictureBox1.Width = 287;

                        //Izrisovanje zivljenj
                        if (_lives == 0)
                        {
                            //GameOver
                            _paused = true;
                            igralnoOkno.Image = _goScreen;


                            if (ScoreTextHandler.reachedHighScore(_points))
                            {
                                RattlerHighScore vnosImena = new RattlerHighScore();
                                vnosImena.ShowDialog();

                                _sth.addNewScore(new Points(_playerName, _points));

                                RattlerHighScores highscores = new RattlerHighScores();
                                highscores.ShowDialog();
                            }
                        }
                        else
                        {
                            continueGame();
                        }
                    }
                    else if (state[0] == 4)
                    {
                        //Napredujemo v novi level
                        _removingSnake = true;
                        if (_level.Snakes[0].Body.Count > 0)
                        {
                            _level.Snakes[0].Body.RemoveAt(0);
                        }
                        if (_level.Snakes[0].Body.Count == 0)
                        {
                            _removingSnake = false;
                            _izbraniLevel++;
                            _level.Level_number++;
                            continueGame();
                        }
                    }
                }
                List<int> zavoji = _level.Snakes[0].getCurves(); //dobimo listo zavojev. Ta lista se pol uporabi pri vizualizaciji

                for (int i = 1; i < state.Count; i++)
                {
                    if (state[i] == 1) //SOVRAŽNIKOVA KAČA JE POPAPCALA JABOLKO
                    {
                        _povecajKaco[i] += 4;
                    }

                    else if (state[i] == -1)
                    {
                        _level.newEnemyGame(1);
                    }
                }
                if (_level.Apples.Count == 0)
                {
                    _doorOpen = true;

                }
                pictureBox1.Width -= 2;

                if (pictureBox1.Width < 50)
                    pictureBox1.BackColor = Color.Red;

                if (pictureBox1.Width == 0)
                {
                    pictureBox1.BackColor = Color.Green;
                    pictureBox1.Width = 287;
                    List<Apple> apples = _level.Apples;
                    Block[,] leveli = _level.Leveli[_izbraniLevel];
                    Apple.generateApples(ref apples, ref leveli);
                    _doorOpen = false;
                }

                igralnoOkno.Invalidate();
            }
        }

        private void highScoresToolStripMenuItem_Click(object sender, EventArgs e)
        {
            RattlerHighScores RHSs = new RattlerHighScores();
            RHSs.Show();
        }

        /// <summary>
        /// Risanje vsebine igralnega okna
        /// Dizajn legokače - Denis Jakoša
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void igralnoOkno_Paint(object sender, PaintEventArgs e)
        {
            if (!_paused)
            {
                for (int i = 0; i < 41; i++)
                {
                    for (int j = 0; j < 41; j++)
                    {
                        //ta if je za stene, da ne povzročimo črne luknje v MB
                        if ((i == 0 || i == 40) || (j == 0 || j == 40))
                        {
                            e.Graphics.DrawRectangle(new Pen(new SolidBrush(Color.Blue)), new Rectangle(i * 7, j * 7, 6, 6));
                            e.Graphics.FillRectangle(new SolidBrush(Color.Blue), new Rectangle(i * 7, j * 7, 5, 5));
                            if (_doorOpen) //Če so vrata odprta
                            {
                                e.Graphics.DrawRectangle(new Pen(new SolidBrush(Color.Black)), new Rectangle(20 * 7, 0 * 7, 6, 6));
                                e.Graphics.FillRectangle(new SolidBrush(Color.Black), new Rectangle(20 * 7, 0 * 7, 5, 5));
                            }
                            continue;
                        }
                        

                        if (_level.Leveli[_izbraniLevel][i, j].State == 2 && !(_level.Leveli[_izbraniLevel][i, j] is BodyPart))
                        {
                            e.Graphics.DrawRectangle(new Pen(new SolidBrush(Color.Blue)), new Rectangle(i * 7, j * 7, 6, 6));
                            e.Graphics.FillRectangle(new SolidBrush(Color.Blue), new Rectangle(i * 7, j * 7, 5, 5));
                        }

                        if (_level.Leveli[_izbraniLevel][i, j] is Apple)
                        {
                            Point loc = new Point(i * 7, j * 7);
                            Apple tmpApple = (Apple)_level.Leveli[_izbraniLevel][i, j];
                            if (tmpApple.IsGold)
                            {
                                ((Apple)_level.Leveli[0][i, j]).decreaseCounter();
                                e.Graphics.DrawImage(_goldApple, loc);
                            }
                            else
                            {
                                e.Graphics.DrawImage(_jabolkoSlika, loc);
                                tmpApple.tryGold(_random4Apples.Next(_randomTest));
                            }
                            //e.Graphics.DrawRectangle(new Pen(new SolidBrush(Color.Red)), new Rectangle(i * 7, j * 7, 6, 6));
                            // e.Graphics.FillRectangle(new SolidBrush(Color.Red), new Rectangle(i * 7, j * 7, 5, 5));
                        }

                        if (_level.Leveli[_izbraniLevel][i, j] is BodyPart)
                        {

                            if (_level.Leveli[_izbraniLevel][i, j] == _level.Snakes[0].Body.ElementAt(0) && !_removingSnake)
                            {
                                _glavaSlika = new Bitmap("../../Resources/snake-head_gfx.png");
                                Point loc = new Point(i * 7, j * 7);
                                if (_level.Snakes[0].Body[0].Smer == 0)
                                {
                                    _glavaSlika.RotateFlip(RotateFlipType.Rotate270FlipNone);
                                }
                                else if (_level.Snakes[0].Body[0].Smer == 2)
                                {
                                    _glavaSlika.RotateFlip(RotateFlipType.Rotate90FlipNone);
                                }
                                else if (_level.Snakes[0].Body[0].Smer == 3)
                                {
                                    _glavaSlika.RotateFlip(RotateFlipType.Rotate180FlipNone);
                                }
                                e.Graphics.DrawImage(_glavaSlika, loc);
                            }
                            else
                            {
                                e.Graphics.DrawRectangle(new Pen(new SolidBrush(Color.Yellow)), new Rectangle(i * 7, j * 7, 6, 6));
                                e.Graphics.FillRectangle(new SolidBrush(Color.Yellow), new Rectangle(i * 7, j * 7, 5, 5));
                            }
                        }

                        if (_level.Leveli[_izbraniLevel][i, j] is Ball)
                        {
                            e.Graphics.DrawRectangle(new Pen(new SolidBrush(Color.Purple)), new Rectangle(i * 7, j * 7, 6, 6));
                            e.Graphics.FillRectangle(new SolidBrush(Color.Purple), new Rectangle(i * 7, j * 7, 5, 5));
                        }

                    }

                    //Izrisovanje dodatnih življenj (metkov haha)
                    switch (_lives)
                    {
                        case 1:
                            pbLifeOne.Visible = false;
                            pbLifeTwo.Visible = false;
                            break;
                        case 2:
                            pbLifeOne.Visible = true;
                            pbLifeTwo.Visible = false;
                            break;
                        case 3:
                            pbLifeOne.Visible = true;
                            pbLifeTwo.Visible = true;
                            break;
                    }
                }/*
            for (int i = 7; i < igralnoOkno.Width; i += 7)
                e.Graphics.DrawLine(new Pen(new SolidBrush(Color.Black)), new Point(0, i), new Point(igralnoOkno.Width, i));

            for (int i = 7; i < igralnoOkno.Height; i += 7)
                e.Graphics.DrawLine(new Pen(new SolidBrush(Color.Black)), new Point(i, 0), new Point(i, igralnoOkno.Height));*/
            }
        }

        /// <summary>
        /// Izbira težavnosti
        /// Denis Jakoša
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void beginnerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            UserSettings.setDifficulty(0);
            beginnerToolStripMenuItem.Checked = true;
            intermediateToolStripMenuItem.Checked = false;
            advancedToolStripMenuItem.Checked = false;
            expertToolStripMenuItem.Checked = false;
            diffucultySetup();
        }

        /// <summary>
        /// Izbira težavnosti
        /// Denis Jakoša
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void intermediateToolStripMenuItem_Click(object sender, EventArgs e)
        {
            UserSettings.setDifficulty(1);
            beginnerToolStripMenuItem.Checked = false;
            intermediateToolStripMenuItem.Checked = true;
            advancedToolStripMenuItem.Checked = false;
            expertToolStripMenuItem.Checked = false;
            diffucultySetup();
        }

        /// <summary>
        /// Izbira težavnosti
        /// Denis Jakoša
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void advancedToolStripMenuItem_Click(object sender, EventArgs e)
        {
            UserSettings.setDifficulty(2);
            beginnerToolStripMenuItem.Checked = false;
            intermediateToolStripMenuItem.Checked = false;
            advancedToolStripMenuItem.Checked = true;
            expertToolStripMenuItem.Checked = false;
            diffucultySetup();
        }

        /// <summary>
        /// Izbira težavnosti
        /// Denis Jakoša
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void expertToolStripMenuItem_Click(object sender, EventArgs e)
        {
            UserSettings.setDifficulty(3);
            beginnerToolStripMenuItem.Checked = false;
            intermediateToolStripMenuItem.Checked = false;
            advancedToolStripMenuItem.Checked = false;
            expertToolStripMenuItem.Checked = true;
            diffucultySetup();
        }

        //Ko klikne na izbiro levela v meniju se odpre okno za izbiro
        private void startingRoomToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LevelSelection oknoLevel = new LevelSelection();
            oknoLevel.SelectedLevel = _izbraniLevel;
            _paused = true;
            oknoLevel.ShowDialog(GUI.ActiveForm);
            _izbraniLevel = oknoLevel.SelectedLevel;
            _paused = false;
            igralnoOkno.Image = null;
            startGame();

        } 

        private void pauseToolStripMenuItem_Click(object sender, EventArgs e)
        {
            _paused = true;
        }

        private void toolStripMenuItem2_Click(object sender, EventArgs e) //0 žogic
        {
            _level.changeBallNumber(0);
            _ballNum = 0;
        }

        private void toolStripMenuItem3_Click(object sender, EventArgs e) //1
        {
            _level.changeBallNumber(1);
            _ballNum = 1;
        }

        private void toolStripMenuItem4_Click(object sender, EventArgs e) //2
        {
            _level.changeBallNumber(2);
            _ballNum = 2;
        }

        private void toolStripMenuItem5_Click(object sender, EventArgs e) //3
        {
            _level.changeBallNumber(3);
            _ballNum = 3;
        }

        private void toolStripMenuItem6_Click(object sender, EventArgs e) //0 kač
        {
            _level.changeEnemyNumber(0);
            _snakeNum = 0;
        }

        private void toolStripMenuItem7_Click(object sender, EventArgs e) //1
        {
            _level.changeEnemyNumber(1);
            _snakeNum = 1;
        }

        private void toolStripMenuItem8_Click(object sender, EventArgs e) //2
        {
            _level.changeEnemyNumber(2);
            _snakeNum = 2;
        }

        private void toolStripMenuItem9_Click(object sender, EventArgs e) //3
        {
            _level.changeEnemyNumber(3);
            _snakeNum = 3;
        }

        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            igralnoOkno.Image = null;
            _lives = 3;
            startGame();
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }
    }
}
